package apibasej.bkp;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;

import apibasej.basic.config.ConfigManager;
import apibasej.basic.misc.UtilTrace;
import apibasej.basic.misc.io.UtilFile;

public abstract class UtilBkp extends ConfigManager{

	// deve ter as barras no final !!!!!
	private String dirRead;
	private String dirWrite;
	
	private File fileLog = null;
	private FileWriter fileWriterLog = null;
	private PrintWriter printWriterLog = null;
	
	protected int ctFilesCopieds = 0;
	protected int ctDirsCreateds = 0;
	protected int ctReferences = 0;
	protected int ctRemoveds = 0;
	protected int ctTotalCurrentPaths = 0;
	protected int ctErros = 0;
	protected long totalSizeFilesRead = 0;
	protected long totalSizeFilesWrite = 0;
	
	//private String fileSeparator;
	private String prefixDate;
	
	private String regexValidFiles;  
	private String prefixLog = "";
	
	public UtilBkp(String dirRead, String dirWrite) {
		this.dirRead = dirRead;
		this.dirWrite = dirWrite;
		this.prefixDate = new SimpleDateFormat("yyyyMMddHHmmss").format(getDateNow());
		
		String fileSeparator = System.getProperty("file.separator");
		if( !this.dirRead.endsWith(fileSeparator)  ) this.dirRead = this.dirRead+fileSeparator;
		if( !this.dirWrite.endsWith(fileSeparator) ) this.dirWrite = this.dirWrite+fileSeparator;
	}

	
	public String getStringSizes(long sizeInBytes){
		float div = (float)1024;
		float kbs = sizeInBytes/div;
		if(kbs<0.001F) kbs=0;// para não mostrar ?.???-6 ...
		float mbs = kbs/div;
		if(mbs<0.001F) mbs=0;
		float gbs = mbs/div;
		if(gbs<0.001F) gbs=0;
		return ""+gbs+" GB, "+mbs+" MB, "+kbs+" KB, "+sizeInBytes+" bytes";
	}
	
	public String getPrefixLog() {
		return prefixLog;
	}
	public void setPrefixLog(String prefixLog) {
		this.prefixLog = prefixLog;
	}
	
	public File getFileLog() {
		if(fileLog==null) {
			fileLog = new File(dirWrite+getPrefixLog()+prefixDate+".log");
			if(!fileLog.getParentFile().exists()) fileLog.getParentFile().mkdirs();
		}
		return fileLog;
	}
	
	public int getCtErros() {
		return ctErros;
	}
	
	public PrintWriter getPrintWriterLog() throws IOException {
		if(fileWriterLog==null) fileWriterLog = new FileWriter(getFileLog());
		if(printWriterLog==null) printWriterLog = new PrintWriter(fileWriterLog);
		return printWriterLog;
	}
	
	public void closeWriterLog(){
		fileLog = null;
		if(printWriterLog!=null) {
			printWriterLog.close();
			printWriterLog = null;
		}
		if(fileWriterLog!=null){
			try {
				fileWriterLog.close();
				fileWriterLog = null;
			} catch (IOException e) {
				printInfo("ERROR ON CLOSE WRITER LOG: "+e.getMessage(),e);
			}
		}
	}

	// exibe informações na console e em um arquivo de informações do backup
	public void printInfo(String info){
		printInfo(info, null);
	}
	public void printInfo(String info, Throwable t){
		if(t!=null) info = "[ERROR]\t"+info;
		System.out.println(info);
		if(t!=null) {
			ctErros++;
			t.printStackTrace();
		}
		try {
			getPrintWriterLog().write(info+"\r\n");
			if(t!=null) getPrintWriterLog().write(UtilTrace.getStackTrace(t)+"\r\n");
			getPrintWriterLog().flush();
		} catch (IOException e) {
			System.out.println("ERROR ON SAVE LOG: "+e.getMessage());
			e.printStackTrace();
		}
	}
	
	public abstract void verifyFileSource(File f) throws Exception;
	public abstract void verifyRemoveds() throws Exception;
	public abstract void beforeBackup() throws Exception;
	public abstract void afterBackup() throws Exception;
	
	
	public void startBkp() throws Exception{
		beforeBackup();
		printInfo("*** START BACKUP: "+new SimpleDateFormat(getProp(PATTERN_DATE_TIME)).format(getDateNow())+" ***");
		printInfo("---------------------------------------------------------------------------");
		printInfo("Analising current files ...");
		UtilFile uf = new UtilFile(){
			@Override
			public void eventAddFile(File f) {
				try {
					ctTotalCurrentPaths++;
					verifyFileSource(f);
				} catch (Exception e) {
					printInfo("ERROR ON VERIFY FILE: "+f.getPath(),e);
				}
			}
		};
		uf.setRegexValidFiles(getRegexValidFiles());
		uf.setAddDirs(true);
		uf.readFilesDirs( new File(getDirRead()).listFiles() );
		printInfo("---------------------------------------------------------------------------");
		printInfo("Verifying removeds ...");
		try {
			verifyRemoveds();// verifica os removidos !!!!
		} catch (Throwable e) {
			printInfo("ERROR ON VERIFY REMOVEDS: "+e,e);
		}
		printInfo("---------------------------------------------------------------------------");
		printInfo("ctFilesCopieds = "+ctFilesCopieds);
		printInfo("ctDirsCreateds = "+ctDirsCreateds);
		printInfo("ctReferences = "+ctReferences);
		printInfo("ctRemoveds = "+ctRemoveds);
		printInfo("ctTotalCurrentPaths = "+ctTotalCurrentPaths);
		printInfo("ctErros = "+ctErros);
		printInfo("totalSizeFilesRead = "+getStringSizes(totalSizeFilesRead) );
		printInfo("totalSizeFilesWrite = "+getStringSizes(totalSizeFilesWrite) );
		
		printInfo("*** END BACKUP: "+new SimpleDateFormat(getProp(PATTERN_DATE_TIME)).format(getDateNow())+" ***");
		
		afterBackup();
		closeWriterLog();
	}
	
	
	
	//public String getFileSeparator() {
	//	return fileSeparator;
	//}
	public String getPrefixDate() {
		return prefixDate;
	}
	public String getDirRead() {
		return dirRead;
	}
	public String getDirWrite() {
		return dirWrite;
	}
	public String getRegexValidFiles() {
		return regexValidFiles;
	}
	public void setRegexValidFiles(String regexValidFiles) {
		this.regexValidFiles = regexValidFiles;
	}

}
